package com.grj.community.all.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.grj.community.all.common.RedisKey;
import com.grj.community.all.common.Result;
import com.grj.community.all.entity.Follow;
import com.grj.community.all.entity.Post;
import com.grj.community.all.entity.User;
import com.grj.community.all.service.FollowService;
import com.grj.community.all.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 14505
 */
@RestController
@RequestMapping("/post")
@RequiredArgsConstructor
public class PostController {
    private final PostService postService;

    private final FollowService followService;

    private final HttpServletResponse httpServletResponse;

    private static Long id = 1L;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @PostMapping("/add")
    public Result<Object> add(@RequestBody Post  post) {
        Long uid = Long.valueOf(httpServletResponse.getHeader("uid"));
        post.setUid(uid);
        boolean save = postService.save(post);
        if(!save){
            return Result.fail("发布失败");
        }
        ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
        List<Follow> followList = followService.list(new LambdaQueryWrapper<Follow>().eq(Follow::getFid, uid).select(Follow::getUid));
        for (Follow follow : followList) {
            ops.add(RedisKey.FEED + follow.getUid(), post.getId(), System.currentTimeMillis());
        }
        return Result.success("发布成功");
    }

    @GetMapping("/list")
    public Result<Object> list() {
        List<Post> list = postService.list();
        ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
        Long uid = Long.valueOf(httpServletResponse.getHeader("uid"));
        List<Post> collect = list.stream().peek(i -> {
            Double score = ops.score(RedisKey.LIKE + i.getId(), uid);
            i.setIsLike(score != null);
        }).collect(Collectors.toList());
        return Result.success(collect);
    }

    @GetMapping("/like/{id}")
    public Result<Object> get(@PathVariable Long id) {
        ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
        Long uid = Long.valueOf(httpServletResponse.getHeader("uid"));
        Double score = ops.score(RedisKey.LIKE + id, uid);
        if(Objects.isNull(score)){
            Post byId = postService.getById(id);
            byId.setLikes(byId.getLikes()+1);
            postService.updateById(byId);
            ops.add(RedisKey.LIKE+id, uid, System.currentTimeMillis());
            return Result.success("点赞成功");
        }
        Post byId = postService.getById(id);
        byId.setLikes(byId.getLikes()-1);
        postService.updateById(byId);
        ops.remove(RedisKey.LIKE+id, uid);
        return Result.success("取消点赞成功");
    }

    @GetMapping("/feed/{n}")
    public Result<Object> feed(@PathVariable Long n) {
        long size= 10L;
        long uid = Long.parseLong(httpServletResponse.getHeader("uid"));
        List<Long> list = Objects.requireNonNull(redisTemplate.opsForZSet().reverseRange(RedisKey.FEED + uid, (n-1)*size, n*size-1)).stream().map(i -> (Long) i).collect(Collectors.toList());
        if(list.size() == 0){
            return Result.success(null);
        }
        List<Post> collect = postService.listByIds(list);
        List<Post> postList = collect.stream().sorted((a, b) -> (int) (b.getId() - a.getId())).collect(Collectors.toList());
        return Result.success(postList);
    }

    @GetMapping("{ids}")
    public Result<Object> getById(@PathVariable Long ids) {
        id++;
        Long uid = Long.valueOf(httpServletResponse.getHeader("uid"));
        Post post = (Post) redisTemplate.opsForHash().get(RedisKey.POST, String.valueOf(id));
        if(post == null){
            post = postService.getById(id);
            redisTemplate.opsForHash().put(RedisKey.POST, String.valueOf(id), post);
        }
        String[] s = DateUtil.now().split(" ");
        Long increment = redisTemplate.opsForHash().increment(RedisKey.VIEW+ s[0], String.valueOf(id), 1);
        post.setViews(increment);
        ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
        Double score = ops.score(RedisKey.LIKE + id, uid);
        Long size = ops.size(RedisKey.LIKE + id);
        post.setIsLike(score!= null);
        post.setLikes(size);
        return Result.success(post);
    }

    @GetMapping("adds")
    public Result<Object> adds() {
        List<Post> list = new ArrayList<>();
        for (long i = 7; i < 11000; i++) {
            Post post = new Post();
            post.setUid(i);
            post.setContext("测试"+i);
            list.add(post);
        }
        return Result.success(postService.saveBatch(list));
    }

    @GetMapping("cache")
    public void cache() {
        List<Post> list = postService.list();
        list.forEach(i->{
            redisTemplate.opsForHash().put(RedisKey.POST, String.valueOf(i.getId()), i);
        });
    }
}
